package com.stylefeng.guns.modular.netcar.controller;

import com.gexin.fastjson.JSON;
import com.gexin.fastjson.JSONObject;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.common.Tools.CodeMsg;
import com.stylefeng.guns.core.common.Tools.Result;
import com.stylefeng.guns.core.common.annotion.BussinessLog;
import com.stylefeng.guns.core.model.Pager;
import com.stylefeng.guns.core.util.HttpUtil;
import com.stylefeng.guns.core.validater.Insert;
import com.stylefeng.guns.core.validater.Update;
import com.stylefeng.guns.modular.netcar.model.OrderInf;
import com.stylefeng.guns.modular.netcar.service.IOrderInfService;
import com.stylefeng.guns.modular.netcar.service.IOrderUserRelationService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 订单信息
 *
 * @author sasazaixian
 * @Date 2018-10-25 18:11
 */
@Controller
@RequestMapping(value = {"/gunsApi/auth/orderInf"})
@Api(value = "订单信息操作相关api", tags = {"订单信息操作接口"})
@Slf4j
public class OrderInfController extends BaseController {
    @Autowired
    private IOrderInfService orderInfService;
    @Autowired
    private IOrderUserRelationService orderUserRelationService;
    @Value("${spring.mobileServerUrl}")
    private String mobileServerUrl;
    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    private final Lock r = rwl.readLock();
    private final Lock w = rwl.writeLock();
    /**
     * 分页获取订单信息列表
     *
     * @param orderInf
     * @param pageNum
     * @param pageSize
     * @return
     */
    @ApiOperation(value = "分页获取订单信息列表", notes = "分页获取订单信息列表", httpMethod = "POST")
    @PostMapping(value = "/pageList", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Result pageList(
            @RequestBody @ApiParam(name = "orderInf", value = "订单信息对象") OrderInf orderInf,
            @ApiParam(name = "pageNum", value = "当前页数", required = true) @RequestParam(value = "pageNum", required = true) Integer pageNum,
            @ApiParam(name = "pageSize", value = "每页显示条数", required = true) @RequestParam(value = "pageSize", required = true) Integer pageSize
    ) {
        try {
            r.lock();
            Pager pager = new Pager();
            pager.setPageNumber(pageNum);//页码从1 开始
            pager.setPageSize(pageSize);
            pager.setObj(orderInf);
            return Result.success(orderInfService.pageListOrderInf(pager, getToken()));
        } catch (Exception e) {
            return Result.error(CodeMsg.SERVER_EXCEPTION, e.getMessage());
        }finally{
            r.unlock();
        }
    }

    /**
     * 获取订单信息列表
     *
     * @param orderInf
     * @return
     */
    @ApiOperation(value = "获取订单信息列表", notes = "获取订单信息列表", httpMethod = "POST")
    @PostMapping(value = "/list", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Result list(
            @RequestBody @ApiParam(name = "orderInf", value = "订单信息对象") OrderInf orderInf) {
        try {
            r.lock();
            return Result.success(orderInfService.selectListOrderInf(orderInf, getToken()));
        } catch (Exception e) {
            return Result.error(CodeMsg.SERVER_EXCEPTION, e.getMessage());
        }finally{
            r.unlock();
        }
    }

    /**
     * 导出查询订单信息列表
     *
     * @param orderInf
     * @return
     */
    @ApiOperation(value = "导出查询订单信息列表", notes = "导出查询订单信息列表", httpMethod = "POST")
    @PostMapping(value = "/exportlist", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Result exportlist(
            @RequestBody @ApiParam(name = "orderInf", value = "订单信息对象") OrderInf orderInf) {
        try {
            r.lock();
            return Result.success(orderInfService.selectExportListOrderInf(orderInf, getToken()));
        } catch (Exception e) {
            return Result.error(CodeMsg.SERVER_EXCEPTION, e.getMessage());
        }finally{
            r.unlock();
        }
    }

    /**
     * 通过主键获取订单信息对象
     *
     * @param id
     * @return
     */
    @ApiOperation(value = "通过主键获取订单信息对象", notes = "通过主键获取订单信息对象", httpMethod = "GET")
    @GetMapping(value = "/getById", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Result getById(
            @ApiParam(name = "id", value = "主键ID", required = true) @RequestParam(value = "id", required = true) String id
    ) {
        try {
            r.lock();
            return Result.success(orderInfService.findOrderInfById(id, getToken()));
        } catch (Exception e) {
            return Result.error(CodeMsg.SERVER_EXCEPTION, e.getMessage());
        }finally {
            r.unlock();
        }
    }

    /**
     * 获取价格里程信息
     *
     * @param lineId
     * @param startpos
     * @param endpos
     * @param sendTime
     * @return
     */
    @ApiOperation(value = "获取价格里程信息", notes = "获取价格里程信息", httpMethod = "GET")
    @GetMapping(value = "/getPriceFromCache", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Result getPriceFromCache(
            @ApiParam(name = "lineId", value = "线路ID", required = true) @RequestParam(value = "lineId", required = true) String lineId,
            @ApiParam(name = "startpos", value = "起点经纬度", required = true) @RequestParam(value = "startpos", required = true) String startpos,
            @ApiParam(name = "endpos", value = "终点经纬度", required = true) @RequestParam(value = "endpos", required = true) String endpos,
            @ApiParam(name = "sendTime", value = "预约时间（yyyy-MM-dd HH:mm）", required = true) @RequestParam(value = "sendTime", required = true) Date sendTime
    ) {
        if (lineId == null || lineId.length() < 10 || startpos == null || startpos.length() < 5 || endpos == null || endpos.length() < 5 || sendTime == null) {
            return Result.error(CodeMsg.SERVER_EXCEPTION, "参数不全");
        }
        try {
            r.lock();
            startpos = java.net.URLDecoder.decode(startpos, "utf-8");
            endpos = java.net.URLDecoder.decode(endpos, "utf-8");
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("lineId", lineId);
            map.put("startpos", startpos);
            map.put("endpos", endpos);
            map.put("sendTime", new SimpleDateFormat("yyyy-MM-dd HH:mm"));
            String result = HttpUtil.doPost(mobileServerUrl + "gunsApi/auth/orderLine/getPriceKmFromCache", map, "utf-8");
            JSONObject jsonResult = JSON.parseObject(result);
            if (jsonResult.containsKey("code")) {
                if (jsonResult.getIntValue("code") == 200) {
                    Map<String, String> mapResult = new HashMap<>();
                    mapResult.put("sprice", jsonResult.getJSONObject("data").getString("sprice"));
                    mapResult.put("eprice", jsonResult.getJSONObject("data").getString("eprice"));
                    mapResult.put("timePrice", jsonResult.getJSONObject("data").getString("timePrice"));
                    mapResult.put("datePrice", jsonResult.getJSONObject("data").getString("datePrice"));
                    mapResult.put("kmPrice", jsonResult.getJSONObject("data").getString("kmPrice"));
                    mapResult.put("km", jsonResult.getJSONObject("data").getString("km"));
                    return Result.success(mapResult);
                } else {
                    return Result.error(CodeMsg.SERVER_EXCEPTION, jsonResult.getString("data"));
                }
            } else {
                return Result.error(CodeMsg.SERVER_EXCEPTION, "缓存服务器未给出正确的返回值");
            }
        } catch (Exception e) {
            return Result.error(CodeMsg.SERVER_EXCEPTION, e.getMessage());
        }finally{
            r.unlock();
        }

    }

    /**
     * 检测坐标点是否在城市区域内
     *
     * @param lineId  线路Id
     * @param pos     经纬度
     * @param cityFlg 城市表示（S:起点，E:终点）
     * @return
     */
    @ApiOperation(value = "检测坐标点是否在城市区域内", notes = "检测坐标点是否在城市区域内", httpMethod = "GET")
    @GetMapping(value = "/checkPointInCity", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Result checkPointInCity(
            @ApiParam(name = "lineId", value = "线路ID", required = true) @RequestParam(value = "lineId", required = true) String lineId,
            @ApiParam(name = "pos", value = "起点经纬度", required = true) @RequestParam(value = "pos", required = true) String pos,
            @ApiParam(name = "cityFlg", value = "城市表示（S:起点，E:终点）", required = true) @RequestParam(value = "cityFlg", required = true) String cityFlg
    ) {
        if (lineId == null || lineId.length() < 10 || pos == null || pos.length() < 5 || !(cityFlg.equals("S") || cityFlg.equals("E"))) {
            return Result.error(CodeMsg.SERVER_EXCEPTION, "参数不全");
        }
        try {
            pos = java.net.URLDecoder.decode(pos, "utf-8");
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("lineId", lineId);
            map.put("pos", pos);
            map.put("cityFlg", cityFlg);
            String result = HttpUtil.doPost(mobileServerUrl + "gunsApi/auth/orderLine/checkPointInCity", map, "utf-8");
            JSONObject jsonResult = JSON.parseObject(result);
            if (jsonResult.containsKey("code")) {
                if (jsonResult.getIntValue("code") == 200) {
                    Map<String, String> mapResult = new HashMap<>();
                    mapResult.put("exists", jsonResult.getJSONObject("data").getString("exists"));
                    return Result.success(mapResult);
                } else {
                    return Result.error(CodeMsg.SERVER_EXCEPTION, jsonResult.getString("message"));
                }
            } else {
                return Result.error(CodeMsg.SERVER_EXCEPTION, "缓存服务器未给出正确的返回值");
            }
        } catch (Exception e) {
            return Result.error(CodeMsg.SERVER_EXCEPTION, e.getMessage());
        }
    }

    /**
     * 新增订单信息数据
     *
     * @param orderInf
     * @param result
     * @return
     */
    @ApiOperation(value = "新增订单信息数据", notes = "新增订单信息数据", httpMethod = "POST")
    @PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @BussinessLog(value = "新增订单信息数据")
    @ResponseBody
    public Result add(@Validated(value = Insert.class) @RequestBody @ApiParam(name = "orderInf ", value = "订单信息对象") OrderInf orderInf, BindingResult result
    ) {
        if (result.hasErrors()) {
            return Result.error(CodeMsg.SERVER_EXCEPTION, "参数异常！");
        }
        try {
            w.lock();
            orderInfService.insertOrderInf(orderInf, getToken(), true);
            return Result.success();
        } catch (Exception e) {
            return Result.error(CodeMsg.SERVER_EXCEPTION, e.getMessage());
        }finally {
            w.unlock();
        }
    }

    /**
     * 乘客下单
     *
     * @param orderInf
     * @return
     */
    @ApiOperation(value = "乘客下单", notes = "乘客下单", httpMethod = "POST")
    @PostMapping(value = "/customeradd", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Result customeradd(@Validated(value = Insert.class) @RequestBody @ApiParam(name = "orderInf", value = "订单信息对象") OrderInf orderInf, BindingResult result
    ) {
        if (result.hasErrors()) {
            return Result.error(CodeMsg.SERVER_EXCEPTION, "参数异常！");
        }
        try {
            w.lock();
            return this.orderInfService.passengerOrder(orderInf);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(CodeMsg.SERVER_EXCEPTION, e.getMessage());
        }finally {
            w.unlock();
        }
    }

    /**
     * 乘客操作订单状态 sasazaixian@163.com 2019-01-04
     *
     * @param oiId
     * @param ope
     * @return
     */
    @ApiOperation(value = "乘客操作订单状态", notes = "乘客操作订单状态", httpMethod = "POST")
    @PostMapping(value = "/customerOpeOrder", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Result customerOpeOrder(
            @ApiParam(name = "oiId", value = "订单ID", required = true) @RequestParam(value = "oiId", required = true) String oiId,
            @ApiParam(name = "ope", value = "操作", required = true) @RequestParam(value = "ope", required = true) String ope,
            @ApiParam(name = "orState", value = "退款状态：0:后台申请 1:乘客申请", required = true) @RequestParam(value = "orState",defaultValue = "0") String orState
    ) {
        try {
            w.lock();    //获取写锁
            OrderInf updateOrderInf = this.orderInfService.selectById(oiId);
            /**保证你在修改对象引用时的线程安全性*/
            if ("cancel".equals(ope)) {
                updateOrderInf.setCiState("2");
            } else if ("paySuc".equals(ope)) {
                updateOrderInf.setPayState("1");
            } else {
                return Result.error(CodeMsg.SERVER_EXCEPTION, "未知操作");
            }
            /**暂用查询字段传递值*/
            updateOrderInf.setKey(orState);
            updateOrderInf.setUpdateTime(new Date());
            orderInfService.updateOrderInf(updateOrderInf, null);
            return Result.success();
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(CodeMsg.SERVER_EXCEPTION, e.getMessage());
        }finally {
            w.unlock();
        }
    }

    /**
     * 更新订单信息数据
     *
     * @param orderInf
     * @param result
     * @return
     */
    @ApiOperation(value = "更新订单信息数据", notes = "更新订单信息数据", httpMethod = "POST")
    @PostMapping(value = "/update", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @BussinessLog(value = "更新订单信息数据")
    @ResponseBody
    public Result update(@Validated(value = Update.class) @RequestBody @ApiParam(name = "orderInf", value = "订单信息对象") OrderInf orderInf, BindingResult result
    ) {
        if (result.hasErrors()) {
            return Result.error(CodeMsg.SERVER_EXCEPTION, "参数异常！");
        }
        try {
            w.lock();
            OrderInf updateOrderInf = new OrderInf();
            //只能修改订单部分数据
            updateOrderInf.setOiId(orderInf.getOiId());
            //备注
            updateOrderInf.setNote(orderInf.getNote());
            //手机
            updateOrderInf.setCiTel(orderInf.getCiTel());
            //姓名
            updateOrderInf.setCiName(orderInf.getCiName());
            //航班起飞时间
            updateOrderInf.setExSendTime(orderInf.getExSendTime());
            //航班落地时间
            updateOrderInf.setExArrTime(orderInf.getExArrTime());
            //预约时间
            updateOrderInf.setCiSendTime(orderInf.getCiSendTime());
            orderInfService.updateOrderInf(updateOrderInf, getToken());
            return Result.success();
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(CodeMsg.SERVER_EXCEPTION, e.getMessage());
        }finally {
            w.unlock();
        }
    }

    /**
     * 取消订单
     *
     * @param id
     * @return
     */
    @ApiOperation(value = "取消订单", notes = "取消订单", httpMethod = "POST")
    @PostMapping(value = "/updateCancel", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @BussinessLog(value = "取消订单")
    @ResponseBody
    public Result updateCancel(@ApiParam(name = "id", value = "主键ID", required = true) @RequestParam(value = "id", required = true) String id) {
        try {
            w.lock();
            OrderInf updateOrderInf = new OrderInf();
            updateOrderInf.setOiId(id);
            updateOrderInf.setCiState("2");
            int i = orderInfService.updateOrderInf(updateOrderInf, getToken());
            log.info("取消订单数量:{} 个", i);
            return Result.success();
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(CodeMsg.SERVER_EXCEPTION, e.getMessage());
        }finally {
            w.unlock();
        }
    }

    /**
     * 删除订单信息数据
     *
     * @param ids
     * @return
     */
    @ApiOperation(value = "删除订单信息数据", notes = "删除订单信息数据", httpMethod = "GET")
    @GetMapping(value = "/delBatch", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @BussinessLog(value = "删除订单信息数据")
    @ResponseBody
    public Result delBatch(
            @ApiParam(name = "ids", value = "主键ID字符数组", required = true) @RequestParam(value = "ids", required = true) String ids
    ) {
        try {
            orderInfService.deleteBatchOrderInf(ids.split(","), getToken());
            return Result.success();
        } catch (Exception e) {
            return Result.error(CodeMsg.SERVER_EXCEPTION, e.getMessage());
        }
    }

    /**
     * 删除订单信息数据
     *
     * @param orderInf
     * @return
     */
    @ApiOperation(value = "删除订单信息数据", notes = "删除订单信息数据", httpMethod = "POST")
    @PostMapping(value = "/del", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @BussinessLog(value = "删除订单信息数据")
    @ResponseBody
    public Result del(@RequestBody @ApiParam(name = "orderInf", value = "订单信息对象") OrderInf orderInf) {
        try {
            orderInfService.deleteOrderInf(orderInf, getToken());
            return Result.success();
        } catch (Exception e) {
            return Result.error(CodeMsg.SERVER_EXCEPTION, e.getMessage());
        }
    }

    /**
     * 获取订单信息的Key-Value列表，用于html的Select数据源
     *
     * @param orderInf
     * @return
     */
    @ApiOperation(value = "获取订单信息的Key-Value列表，用于html的Select数据源", notes = "获取订单信息的Key-Value列表，用于html的Select数据源", httpMethod = "POST")
    @PostMapping(value = "/optionsList", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Result optionsList(@RequestBody @ApiParam(name = "orderInf", value = "订单信息对象") OrderInf orderInf) {
        try {
            return Result.success(orderInfService.optionsOrderInf(orderInf, getToken()));
        } catch (Exception e) {
            return Result.error(CodeMsg.SERVER_EXCEPTION, e.getMessage());
        }
    }

    /**
     * 获取当期调度的新订单数量
     * @return
     */
    @ApiOperation(value = "获取当期调度的新订单数量", notes = "获取当期调度的新订单数量", httpMethod = "GET")
    @GetMapping(value = "/getNewOrderNum", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Result getNewOrderNum() {
        try {
            Map<String,Integer> map=new HashMap();
            map.put("orderCnt",orderInfService.getNewOrderNum(getToken()));
            return Result.success(map);
        } catch (Exception e) {
            return Result.error(CodeMsg.SERVER_EXCEPTION, e.getMessage());
        }
    }
    /**
     * 清理当期调度的新订单数量
     * @return
     */
    @ApiOperation(value = "清理当期调度的新订单数量", notes = "清理当期调度的新订单数量", httpMethod = "GET")
    @GetMapping(value = "/clearNewOrderNum", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Result clearNewOrderNum() {
        try {
            orderInfService.clearNewOrderNum(getToken());
            return Result.success();
        } catch (Exception e) {
            return Result.error(CodeMsg.SERVER_EXCEPTION, e.getMessage());
        }
    }
    private String getToken() {
        return getHttpServletRequest().getHeader("Authorization").substring(7);
    }
}
